<!--
禁止修改!此文件是产品代码的一部分，后续可能变更或者不再开放。
若有问题，请参考前端相关二开文档。
-->
<template>
  <div class="login-account" :class="{ 'login-err-box': passwordErr }">
    <div class="login-account-login">
      <img src="./logo.jpg" />
      <div class="welcome-text">
        <span>欢迎使用奥哲·云枢</span>
      </div>
    </div>
    <div class="login-account-form">
      <login-input
        v-model="userName"
        :placeholder="'请输入账号'"
        :lable="'账号'"
        :type="'text'"
        @change="becanLogin"
      />

      <login-input
        v-model="passWord"
        :placeholder="'请输入密码'"
        :lable="'账号密码'"
        class="login-last-input"
        :type="'password'"
        @change="becanLogin"
      />

      <div class="login-forget-tips clearfix">
        <span @click="toggle">忘记密码</span>
      </div>

      <login-input
        v-if="verificationType"
        v-model="verification"
        :placeholder="'请输入验证码'"
        :lable="'验证码'"
        class="login-last-input"
        :type="'verification'"
        :canSendMsg="userName && passWord"
        :sendingMessage="sendingMessage"
        @change="becanLogin"
        @sendMsg="sendMsg"
      />
    </div>

    <div
      class="login-account-button"
      :class="{ verification: verificationType }"
    >
      <h3-button
        :disabled="!(userName && passWord && passWord.length >= 2)"
        type="primary"
        @click="login"
      >
        登&nbsp;录
      </h3-button>
    </div>

    <div>
      <h3-modal v-model="showToast" class="dialog-main" :showCancel="false">
        <div slot="default" class="dialog-content">
          <p>请联系系统管理员重置密码</p>
        </div>

        <!-- <div slot="footer" class="dialog-footer">
          <span @click="showToast = false">确定</span>
        </div> -->
        <!-- <div @click="showToast=false">
          <span class="h3-close"></span>
        </div> -->
      </h3-modal>
    </div>
    <div>
      <h3-modal v-model="showTips" class="dialog-main">
        <!-- <div> -->
        <div slot="default" class="dialog-content">
          <p>请先选择组织</p>
        </div>
        <!-- <div class="dialog-footer">
            <span @click="showTips = false">确定</span>
          </div> -->
        <!-- </div> -->
      </h3-modal>
    </div>

    <div class="switch-org">
      <span class="tips">当前组织</span>
      <span class="org-name">{{ orgName.label }}</span>
      <span class="switch-btn" @click="switchOrgShow = true">切换组织</span>
      <H3Popup
        v-model="switchOrgShow"
        maskClosable
        popupDirection="up"
        round
        wrapCls="switch-org-box"
      >
        <div class="header">
          <span
            class="cancel-btn"
            @click="
              () => {
                switchOrgShow = false;
                autoSelect = orgName;
              }
            "
          >
            取消
          </span>
          <span class="title">选择组织</span>
          <span
            class="confirm-btn"
            @click="
              () => {
                onChange(autoSelect);
                switchOrgShow = false;
              }
            "
          >
            确定
          </span>
        </div>
        <div class="body">
          <div
            v-for="org in options"
            :key="org.key"
            class="org-item"
            :class="{
              selected: org.key === autoSelect.key,
            }"
            @click="
              () => {
                autoSelect = org;
              }
            "
          >
            <span class="org-name">{{ org.label }}</span>
            <span
              v-if="org.key === autoSelect.key"
              class="selected-icon aufontAll h-icon-all-check"
            ></span>
          </div>
        </div>
      </H3Popup>
    </div>
  </div>
</template>
<script lang="ts">
import env from '@/config/env';
import common from 'cloudpivot/common';
import Axios from 'axios';
import { H3RadioList } from 'h3-mobile-vue';
import { H3Button, H3Popup, H3Modal } from '@h3/thinking-ui';
import H3Dialog from 'h3-mobile-vue/src/components/h3-dialog/index';
import { Component, Prop, Vue } from 'vue-property-decorator';
import LoginInput from './login-input.vue';
import OAuthApi from './oauth-api';
import { filterUserInfo } from 'cloudpivot/common/src/utils/filter-userInfo';

enum loginError {
  passwordErr = 1000,
  overThreeErr = 10001,
}

enum LoginType {
  OnlyAccount = 0, // 只允许账户密码
  OnlyQrCode = 1, // 只允许扫码
  BothAccountAndQrCode = 2, // 二者均可
  VerificationCode = 3, // 账户密码验证码校验登录
}

@Component({
  name: 'login-account',
  components: {
    LoginInput,
    H3Button,
    H3Dialog,
    H3Modal,
    H3RadioList,
    H3Popup,
  },
})
export default class LoginAccount extends Vue {
  @Prop({
    default: false,
  })
  toggleMode!: boolean;

  redirectUrl: string = ''; // 登陆回跳地址

  getTokenParams: any = {
    code: '',
    url: '',
    client_secret: '',
    client_id: '',
    redirect_uri: '',
  };

  depts: any[] = [];

  deptId: string = '';

  corpId = '';

  config: any = null;

  options: any = [];

  orgName: any = {};

  showModal: boolean = false;

  autoSelect: any = {};

  showTips: boolean = false;

  switchOrgShow: boolean = false;

  show() {
    this.showModal = true;
  }

  close() {
    this.showModal = false;
  }

  onChange(value: any) {
    console.log(value);
    if (value && value.key && value.label) {
      this.onDeptChange(value.key, value.label);
    }
  }

  passwordErr: boolean = false; // 账户密码错误

  passwordType: string = 'password'; // 密码的展示形式

  showPassword: boolean = false;

  overflowTips: boolean = false; // 密码输入已超过3次提示

  loginDisabled: boolean = false; // 登录禁用状态

  userName: string = ''; // 登录账号

  passWord: string = ''; // 登录密码

  verification: string = ''; // 验证码

  sendingMessage: boolean = false;

  visible: boolean = false; // 忘记密码提示窗

  get verificationType() {
    let loginType = -1;
    const config = this.$store.state.config;
    loginType = config.loginType;
    if (~loginType) {
      return [LoginType.VerificationCode].includes(loginType);
    } else {
      return false;
    }
  }

  async mounted() {
    const res: any = await OAuthApi.getDepts();
    if (res.errcode !== 0) {
      this.showError(res.errmsg);
      return;
    }

    this.depts = res.data;
    this.options = [];
    let optList = {};
    res.data.forEach((r: any) => {
      optList = {
        key: r.corpId,
        // value: r.name || '主组织',
        value: r.corpId,
        label: r.name || '主组织',
      };
      this.options.push(optList);
    });
    this.orgName = this.options[0];
    this.autoSelect = this.options[0];
    if (this.depts.length > 0) {
      let deptId = this.depts[0].corpId;
      if (this.$route.query.deptId) {
        deptId = this.$route.query.deptId;
      }
      this.deptId = deptId;
      this.onDeptChange(this.deptId, this.depts[0].name);
    }
  }

  onDeptChange(deptId: string, name: string) {
    const dept = this.depts.find((d) => d.corpId === deptId);
    if (!dept) {
      this.showError('找不到组织机构记录');
      return;
    }
    this.corpId = dept.corpId;
    this.orgName = {
      key: dept.corpId,
      value: dept.corpId,
      label: dept.name || '主组织',
    };
  }

  created() {
    this.generateUrls();
  }

  /**
   * 初始化地址和固定传参
   */
  generateUrls() {
    const { oauthHost, client_id, scope, secret, redirectHost } = env;
    if (secret) {
      // 回跳地址
      this.redirectUrl = `${oauthHost}/login?redirect_uri=${encodeURIComponent(
        `${oauthHost}/oauth/authorize?client_id=${client_id}&response_type=code&scope=${scope}&redirect_uri=${redirectHost}/oauth`,
      )}`;
      // 请求token参数
      this.getTokenParams = {
        code: '',
        url: oauthHost,
        client_secret: secret,
        client_id: client_id,
        redirect_uri: `${redirectHost}/oauth`,
      };
    } else {
      setTimeout(() => {
        this.generateUrls();
      }, 100);
    }
  }

  passwordVisible() {
    if (this.showPassword) {
      this.passwordType = 'password';
    } else {
      this.passwordType = 'text';
    }
    this.showPassword = !this.showPassword;
  }

  becanLogin() {
    // ;
    if (this.userName && this.passWord) {
      this.loginDisabled = true;
    } else {
      this.loginDisabled = false;
    }
    if (this.verification) {
      this.verification = this.verification.slice(0, 6);
    }
  }

  /**
   * 账户密码登录
   */
  async login() {
    if (!this.loginDisabled) {
      return;
    }
    if (this.verificationType && !this.verification) {
      this.showError('验证码不能为空');
      return;
    }
    this.passwordErr = false;
    const { password, index } = (await this.encryption()) as any;
    const params: any = {
      corpId: this.corpId,
      username: this.userName,
      password,
      url: this.redirectUrl,
      portal: true,
      index,
    };
    if (this.verificationType) {
      params.verification_code = this.verification;
    }
    const res = await OAuthApi.login(params);
    if (res.errcode === 200 && res.code) {
      this.getTokenParams.code = res.code;
      this.getToken(this.getTokenParams);
    } else if (res.errcode === loginError.passwordErr) {
      this.passwordErr = true;
      this.showError('用户名或密码错误，请重新输入');
    } else if (res.errcode === loginError.overThreeErr) {
      this.passwordErr = true;
      this.overflowTips = true; // 超过3次
      this.showError('密码输入错误已超过3次,请1分钟后再尝试');
    } else if (res.errcode === 1001) {
      this.showError(res.errmsg);
    } else if (res.errcode === 100011) {
      this.showError('验证码输入错误');
    } else {
    }
  }

  showError(text: string) {
    this.$h3.toast.show({
      text,
      autoHide: true,
      iconType: text.length < 8 ? 'close' : '',
    });
  }

  /**
   * 获取token
   */
  async getToken(params: any) {
    const res = await OAuthApi.getToken(params);
    if (res && res.success) {
      // ;
      const token = (res as any).access_token;
      const refresh_tokens = (res as any).refresh_token;
      const expireTime = (res as any).exp;

      localStorage.setItem('refresh_token', refresh_tokens);
      localStorage.setItem('expireTime', expireTime);
      localStorage.setItem('token', token);
      localStorage.setItem('login_jump', 'false');

      //token有效时长,按小时算
      const activeHour = Math.ceil((res as any).expires_in / 3600) + '';
      localStorage.setItem('activeHour', activeHour);

      await this.getUserInfo();
      const isShowEmailResquest = localStorage.getItem('isShowEmailResquest');
      if (isShowEmailResquest) {
        window.location.href = isShowEmailResquest;
      } else {
        this.$router.push({ name: 'home' }).catch((err: any) => {
          console.log(err);
        });
      }
    }
  }

  showToast = false;

  toggle() {
    // this.showError('请联系系统管理员重置密码');
    this.showToast = true;
  }

  async getUserInfo() {
    const res: any = await OAuthApi.getUserInfo();
    if (res.errcode === 0) {
      const info: any = res.data;
      sessionStorage.setItem('user', JSON.stringify(filterUserInfo(info)));
    }
  }

  async encryption() {
    // rsa加密
    const result = await OAuthApi.getRsaKey();
    const flag: boolean =
      typeof result === 'object' &&
      result.hasOwnProperty('index') &&
      result.hasOwnProperty('key');
    if (!flag) {
      return;
    }
    const { index, key } = result;
    const password: any = common.utils.RsaEncrypt(this.passWord, key);
    // rsa加密结束
    return {
      password,
      index,
    };
  }

  clickedSendBtn: boolean = false;

  remainingTime: number = 0;

  /**
   * 获取验证码
   */
  async sendMsg() {
    if (this.clickedSendBtn) {
      return;
    } else {
      this.clickedSendBtn = true;
    }

    this.passwordErr = false;

    const { password, index } = (await this.encryption()) as any;
    const params: any = {
      corpId: this.corpId,
      username: this.userName,
      password,
      url: this.redirectUrl,
      portal: true,
      index,
    };
    const res = await OAuthApi.getVerificationCode(params);
    if (res.errcode === 100000 || res.errcode === 100001) {
      this.passwordErr = true;
      this.showError('用户名或密码错误，请重新输入');
    } else if (res.errcode === 100003) {
      this.showError(res.errmsg);
    } else if (res.errcode === 100005) {
      this.showError('频繁发送，1分钟只能发送一次');
    } else if (res.errcode === 100012) {
      this.showError('发送验证码失败');
    } else if (res.errcode === 201006) {
      this.showError('用户绑定手机号无效');
    } else if (res.errcode === 999999) {
      this.showError('验证码模式未开启');
    } else {
      this.sendingMessage = true;
      this.remainingTime = 60;
      this.$h3.toast.show({
        text: `验证码已发送至手机${res.data}`,
        autoHide: true,
      });
      const sendMessageInterval = setInterval(() => {
        this.remainingTime--;
        if (!this.remainingTime) {
          this.sendingMessage = false;
          clearInterval(sendMessageInterval);
        }
      }, 1000);
    }

    this.clickedSendBtn = false;
  }
}
</script>
<style lang="less" scoped>
@import '~cloudpivot/common/styles/mixins.less';
.login-account {
  background: #fff;
  overflow: hidden;
  height: 100%;
  .login-account-login {
    padding-top: 50px;
    padding-bottom: 30px;
    img {
      width: 42px;
      height: 42px;
      border-radius: 8px;
      margin-bottom: 20px;
    }
    .welcome-text {
      height: 40px;
      font-size: 24px;
      font-weight: 600;
      color: #111218;
      line-height: 40px;
    }
  }
  .login-account-form {
    margin: 0 40px;
    position: relative;
    .login-last-input {
      margin-top: 16px;
    }
  }
  .login-account-button {
    margin: 0 40px;
    margin-top: 65px;
    /deep/.h3think-button.h3think-button--primary {
      background: #2970ff;
      border-radius: 6px;
      color: #fff;
      &.h3think-button--disabled {
        background: rgba(41, 112, 255, 0.5);
      }
    }
    &.verification {
      margin-top: 49px;
    }
  }
  .login-forget-tips {
    position: absolute;
    width: 52px;
    height: 17px;
    font-size: 13px;
    font-weight: 400;
    color: rgba(17, 18, 24, 0.5);
    line-height: 17px;
    right: 0;
    top: 128px;
  }
  .dialog-main {
    border-radius: 7px;
    .dialog-footer {
      span {
        line-height: 50px;
        color: @primary-color;
        font-size: 17px;
      }
      position: relative;
      .hairline('top', rgba(221, 221, 221, 1));
    }
    .dialog-content {
      min-height: 85px;
      display: flex;
      justify-content: center;
      // justify-items: center;
      align-items: center;
      p {
        font-size: 15px;
        color: rgba(51, 51, 51, 1);
      }
    }
  }

  .switch-org {
    position: absolute;
    bottom: 42px;
    width: 100%;
    height: 20px;
    font-size: 15px;
    font-weight: 400;
    color: rgba(17, 18, 24, 0.5);
    line-height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    .tips {
      margin-right: 4px;
    }
    .org-name {
      display: inline-block;
      max-width: 150px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      margin-right: 17px;
    }
    .switch-btn {
      color: #2970ff;
      position: relative;
      &::before {
        content: ' ';
        display: inline-block;
        width: 0.5px;
        height: 16px;
        background: rgba(17, 18, 24, 0.25);
        position: absolute;
        top: 2px;
        left: -8px;
        z-index: 1;
      }
    }
  }
}
</style>
<style lang="less">
.switch-org-box {
  max-height: calc(100% - 44px);
  .header {
    height: 56px;
    position: relative;
    text-align: center;
    .cancel-btn {
      position: absolute;
      top: 16px;
      left: 16px;
      display: inline-block;
      height: 24px;
      font-size: 16px;
      font-weight: 400;
      color: #2970ff;
      line-height: 24px;
    }
    .title {
      display: inline-block;
      height: 56px;
      font-size: 17px;
      font-weight: 600;
      color: #121933;
      line-height: 26px;
      padding: 15px 0;
    }
    .confirm-btn {
      position: absolute;
      top: 16px;
      right: 16px;
      display: inline-block;
      height: 24px;
      font-size: 16px;
      font-weight: 400;
      color: #2970ff;
      line-height: 24px;
    }
  }
  .body {
    padding: 2px 8px;
    .org-item {
      height: 36px;
      border-radius: 4px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 8px;
      .org-name {
        display: inline-block;
        height: 20px;
        font-size: 14px;
        font-weight: 400;
        color: #111218;
        line-height: 20px;
      }
      &.selected {
        background: #f2f6ff;
        .org-name {
          font-weight: 600;
          color: #2970ff;
        }
        .selected-icon {
          display: inline-block;
          width: 14px;
          height: 14px;
          line-height: 14px;
          font-size: 14px;
          color: #2970ff;
        }
      }
      & + .org-item {
        margin-top: 4px;
      }
    }
  }
}
.dialog-content {
  height: 22px;
  font-size: 15px;
  font-weight: 400;
  color: #121933;
  line-height: 22px;
}
</style>
